import { CreepRole, RoleDatas } from "@/role/types/role";
import { useCache } from "@/utils";
import CreepController from "../controller"


class RoleWorker {

    /**
     * 快死时的后事处理
     * 将资源存放在对应的地方
     * 存完了就自杀
     *
     * @param creep manager
     * @param sourceId 能量存放处
     */
    static deathPrepare(creep: Creep): false {
        if (creep.store.getUsedCapacity() > 0) {
            for (const resourceType in creep.store) {
                let target: StructureWithStore
                // 不是能量就放到 terminal 里
                if (resourceType != RESOURCE_ENERGY && resourceType != RESOURCE_POWER && creep.room.terminal) {
                    target = creep.room.terminal
                }
                // 否则就放到 storage 或者玩家指定的地方
                else target = creep.room.storage
                // 刚开新房的时候可能会没有存放的目标
                if (!target) return false

                // 转移资源
                creep.goTo(target.pos)
                creep.transfer(target, <ResourceConstant>resourceType)

                return false
            }
        }
        else creep.suicide()

        return false
    }

    /**
     *
     * @param creep
     * @returns
     */
    static loop(creep: Creep) {

        if (creep.ticksToLive <= 40) {
            return RoleWorker.deathPrepare(creep)
        }

        const memoryData: RoleDatas[CreepRole.Worker] = creep.memory.data as RoleDatas[CreepRole.Worker]

        if (!memoryData) {
            creep.log('memory error')
            return
        }

        if (creep.memory.working && creep.store[RESOURCE_ENERGY] == 0) {
            creep.memory.working = false;
            creep.say('🔄 withdraw');
        }
        if (!creep.memory.working && creep.store[RESOURCE_ENERGY] >= 50) {
            creep.memory.working = true;
            creep.say('🚧 build');
        }

        if (creep.memory.working) {

            if (!creep.memory.targetId && !creep.memory.repairStructureId) {
                // build
                const constructionSite = creep.room.find(FIND_CONSTRUCTION_SITES)[0] as ConstructionSite
                if (constructionSite) {
                    creep.memory.targetId = constructionSite.id
                }
            }

            if (!creep.memory.targetId && !creep.memory.repairStructureId) {
                // 找到受损建筑
                const target: AnyStructure = useCache(() => {
                    const damagedStructures = creep.room.find(FIND_STRUCTURES, {
                        filter: s => s.hits < s.hitsMax &&
                            // 墙壁在刷墙任务里维护
                            s.structureType != STRUCTURE_RAMPART &&
                            s.structureType != STRUCTURE_WALL
                    })
                    // 找到最近的受损建筑并更新缓存
                    if (damagedStructures.length > 0) return creep.pos.findClosestByRange(damagedStructures)
                }, creep.memory, 'repairStructureId')
                // 没有需要维修的建筑，任务完成
                if (!target) {
                    delete creep.memory.repairStructureId
                }
                else {
                    creep.memory.repairStructureId = target.id
                }
            }

            if (creep.memory.targetId) {
                let constructionSite: ConstructionSite;
                constructionSite = Game.getObjectById(creep.memory.targetId) as ConstructionSite
                if (constructionSite) {
                    const status = creep.build(constructionSite)
                    if (status == ERR_NOT_IN_RANGE) {
                        creep.goTo(constructionSite.pos)
                        return
                    }
                    else if (status == ERR_INVALID_TARGET || status == OK) {
                        delete creep.memory.targetId
                    }
                    return
                }
                if (!constructionSite) {
                    delete creep.memory.targetId
                }
            }

            if (creep.memory.repairStructureId) {
                // 修满了就换建筑
                const target = Game.getObjectById(creep.memory.repairStructureId)

                if (target.hits >= target.hitsMax) {
                    delete creep.memory.repairStructureId
                }
                const status = creep.repair(target)
                if (status == ERR_NOT_IN_RANGE) {
                    creep.goTo(target.pos)
                }
                else if (status == OK) {
                    delete creep.memory.repairStructureId
                }
                creep.say('W->R')
                return
            }

            creep.upgradeRoom(creep.room.name)
            creep.say('W->U')
            return
        }
        else {
            if (creep.store.getFreeCapacity(RESOURCE_ENERGY) > 0 && creep.ticksToLive > 50) {

                if (!creep.memory.targetId) {
                    const storeObj = CreepController.findStorage(creep, 200)
                    if (storeObj) {
                        creep.memory.targetId = storeObj.id
                    }
                    else {
                        const container = CreepController.findContainer(creep, 200)
                        if (container) {
                            creep.memory.targetId = container.id
                        }
                        else {
                            const resource = CreepController.findResourceDropped(creep, 100)
                            if (resource) {
                                creep.memory.targetId = resource.id
                            }
                        }
                    }
                }

                if (creep.memory.targetId) {
                    const storeObj = Game.getObjectById(creep.memory.targetId) as StructureWithStore
                    if (storeObj) {
                        creep.goTo(storeObj.pos)
                        const status = creep.withdraw(storeObj, RESOURCE_ENERGY)
                        if (status == OK) {
                            delete creep.memory.targetId
                        }
                        return
                    }
                }
                else if (memoryData.resourceId) {
                    const resource = Game.getObjectById(memoryData.resourceId) as Resource
                    if (resource) {
                        creep.goTo(resource.pos)
                        const status = creep.pickup(resource)
                        if (status == OK) {
                            delete memoryData.resourceId
                        }
                        return
                    }
                }
            }
        }
    }
}

export default RoleWorker
